/** 
 * Links:compute links between to points
 * input file:
 *   simMatrixPath: keyword,weight,[(keyword_i,sim_i)(keyword_j,sim_j)...] \n
 * output file:
 *   linksMatrixPath: keyword,weight,[(keyword_i,neighbors_num_i)(keyword_j,neighbors_num_j)...]\n
 */
package cluster;
import java.io.*;
import java.util.ArrayList;
import common.Word;
import common.Config;
import preprocess.SimItem;
import preprocess.SimRecord;

class LinkItem{
	public String keyword;
	public int num;
	public LinkItem( String keyword,int num ){
		this.keyword = keyword;
		this.num = num;
	}
    public String toString(){
        return "("+keyword+","+num+")";
    }
}

class LinkRecord{
	public String keyword;
    public float weight;
	public ArrayList<LinkItem> linkList = new ArrayList<LinkItem>();
    public LinkRecord( Word w ){
        this.keyword = w.keyword;
        this.weight = w.weight;
    }
    public String toString(){
        return keyword+","+weight+","+linkList.toString();
    }
}

public class Links{
	private ArrayList<LinkRecord> linksMatrix = new ArrayList<LinkRecord>();

    /**
     * 将[(keyword,sim),(..,..)...]型字符串转换成ArrayList
     */
	private ArrayList<SimItem> strToList( String str ){
		ArrayList<SimItem> slist = new ArrayList<SimItem>();
		try{
			str = str.trim().substring( 2,str.length()-2 );
			for( int i=0;i<str.length();i++ ){
				//test
				String[] pair = str.split("), (");
				for( int j=0;j<pair.length;j++){
					String[] items = pair[i].split(",");
					slist.add( new SimItem( items[0],Float.parseFloat(items[1]) ));
				}
			}
		}catch( IndexOutOfBoundsException e ){
			System.out.println( "data formart wrong,cannot transform to ArrayList:"+str);
		}
		return slist;
	}

	private ArrayList< SimRecord> readData() throws IOException{
		String path = Config.simMatrixPath;
		ArrayList< SimRecord > simMatrix = new ArrayList< SimRecord >();

		try{
			FileReader fr = new FileReader( path );
			BufferedReader br = new BufferedReader( fr );

			String line = br.readLine();
			int lineno = 0;
			while( line != null ){
				String[] items = line.trim().split(",",3);
				try{
					SimRecord sr = new SimRecord( items[0],Float.parseFloat( items[1] ) );
					sr.colist = strToList( items[3] );
					simMatrix.add( sr );
				}catch( NumberFormatException e ){
					System.err.println( "Wrong record:"+line +""+e.toString());
				}
				lineno++;
				line = br.readLine();
			}
			br.close();
			fr.close();
		}catch( FileNotFoundException e ){
			System.err.println( path + " not found!" );
			System.exit(1);
		}
		return simMatrix;
	}
    /**
     * request link record by keyword,if not exsit,create it with word and 
     * weight info
     */
    private LinkRecord requestLinkRecord( Word word ){
        // find record whose keyword equal word
        for( int i=0;i<linksMatrix.size();i++ ){
            if( linksMatrix.get(i).keyword.equals( word.keyword ) ){
                return linksMatrix.get(i);
            }
        }
        // not find,new one and then add it
        return new LinkRecord( word );
    }
    /**
     * add keyword to li,if already exsit,increasing the recounter
     */
    private void addSingleLink( ArrayList<LinkItem> li,String keyword ){
        // find whether a LinkItem contain this keyword
        for( int i=0;i<li.size();i++ ){ 
            LinkItem item = li.get(i);
            if( item.keyword.equals(keyword) ){
                item.num++;
                return;
            }
        }
        // not found,new a entry
        LinkItem newit = new LinkItem( keyword,1 );
        li.add( newit );
    }
    /**
     * add link relationship both for lr and another
     */
    private void addLink( LinkRecord lr,LinkRecord another ){
        addSingleLink( lr.linkList,another.keyword );
        addSingleLink( another.linkList,lr.keyword );
    }

    /**
     * give a keyword's correlate keywords list,compute links between
     * keywords pairs in list
     */
    private void trackLinks( ArrayList<Word> words ){
        for( int i=0;i<words.size();i++ ){
            LinkRecord lr = requestLinkRecord( words.get(i) );
            for( int j=i;j<words.size();j++ ){
                LinkRecord another = requestLinkRecord( words.get(j) );
                addLink( lr,another );
            }
        }
    }

	private void computeLinks( ArrayList<SimRecord> simMatrix ){
		for( int i=0;i<simMatrix.size();i++ ){
            SimRecord sr = simMatrix.get( i );
            ArrayList<Word> words = sr.extractWords();
            trackLinks( words );
        }
	}

    private void writeResult() throws IOException{
        FileWriter fw = new FileWriter( Config.linksMatrixPath );
        for( int i=0;i<linksMatrix.size();i++ ){
            fw.write( linksMatrix.get(i).toString()+"\n" );
        }
        fw.close();
    }

	public void run() throws IOException{
		ArrayList<SimRecord> simMatrix = readData();
        System.out.println("readData finished!");
        computeLinks( simMatrix );
		System.out.println("computeLinks finished!");
        writeResult();
		System.out.println("writeResult finished!");
    }

    public static void main( String[] args ) throws IOException{
        Links mylinks = new Links();
		mylinks.run();		
		System.out.println("Completed!");
    }
}